home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / src / net / bind-contrib.tar.gz / bind-contrib.tar / contrib / nutshell / ch09.check_del.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-25  |  11.1 KB  |  504 lines

  1. /*
  2. ** Program to verify subdomain delegation
  3. ** (for use with BIND 4.9.3)
  4. ** 
  5. ** Paul Albitz
  6. ** Hewlett Packard
  7. **
  8. ** usage: check_del [-v] [-F] [-o origin] -f dns_file [-o origin] \
  9. **                                                      [-f dns_file ...]
  10. **
  11. **    -v            print out successes as well as failures.  This argument
  12. **                  must appear before the -f argument.  If -v is used twice, 
  13. **                  check_del prints out the address used and the response packet.
  14. **    -F            fast mode - cuts down the retransmission wait time.  This
  15. **                  argument must appear before the -f argument.
  16. **    -o origin     same use as origin in BIND's boot file
  17. **    -f dns_file   file in RFC 1035 format
  18. **
  19. **  Build in the named directory with this command:
  20. **       cc -o check_del -I../include -I../compat/include ch09.check_del.c \
  21. **                                     db_load.c db_glue.c ../res/libresolv.a
  22. **
  23. **  On SYSV or SYSV-derived operating systems, define SYSV at compile
  24. **  time (-DSYSV).
  25. **
  26. */
  27.  
  28. #include <sys/types.h>
  29. #include <sys/socket.h>
  30. #include <sys/time.h>
  31. #include <netinet/in.h>
  32. #include <signal.h>
  33. #include <stdio.h>
  34. #include <errno.h>
  35. #include <signal.h>
  36. #include <syslog.h>
  37. #include <ctype.h>
  38. #include <netdb.h>
  39. #include <arpa/nameser.h>
  40. #include <resolv.h>
  41.  
  42. #include "named.h"
  43.  
  44. /*
  45. ** These variables are needed by db_load.c.
  46. */
  47. int errs = 0;
  48. struct __res_state res_save;
  49. struct zoneinfo zone, *zones = &zone;    /* zone information */
  50. struct hostent *hp;
  51. int debug = 0;
  52. int max_cache_ttl = 300;
  53. struct    timeval tt;
  54. FILE *ddt = NULL;
  55. struct hashbuf *hashtab;    /* root hash table */
  56. struct hashbuf *fcachetab;    /* hash table of cache read from file */
  57. struct sockaddr_in sin;
  58. int lineno;
  59.  
  60. /*
  61. ** These variables are used by this program.
  62. */
  63. char query[PACKETSZ];
  64. char response[PACKETSZ];
  65. int verbose = 0;
  66. extern int errno;
  67. char *string_resp[200];
  68. char *string_maybe[200];
  69. char *string_run[200];
  70. int noresponse = 0;
  71. int notrunning = 0;
  72. int mayberunning = 0;
  73. int goodresp = 0;
  74. int badresp = 0;
  75. int servfail = 0;
  76.  
  77.  
  78. dostats()
  79. {
  80.     int j;
  81.  
  82.     printf("\n");
  83.     if(goodresp > 0)
  84.         printf("%d proper domain delegations\n", goodresp);
  85.     if(badresp > 0)
  86.         printf("%d improper domain delegations\n", badresp);
  87.     if(servfail > 0)
  88.         printf("%d SERVFAIL answers\n", servfail);
  89.     if(notrunning > 0)
  90.         printf("%d servers not running\n", notrunning);
  91.     if(noresponse > 0)
  92.         printf("%d servers not responding\n", noresponse);
  93.     if(notrunning > 0){
  94.         printf("\nServers not running:\n");
  95.         for(j = 0; j < notrunning; j++)
  96.         printf("\t%s\n", string_run[j]);
  97.     }
  98.     if(noresponse > 0){
  99.         printf("\nServers not responding:\n");
  100.         for(j = 0; j < noresponse; j++)
  101.         printf("\t%s\n", string_resp[j]);
  102.     }
  103.     exit(errs);
  104. }
  105.  
  106. usage()
  107. {
  108.     fprintf(stderr, "check_del [-v] [-F] [-o origin] -f db_file [-o origin] [-f db_file]\n");
  109.     exit(1);
  110. }
  111.  
  112. main(argc, argv)
  113. int argc;
  114. char *argv[];
  115. {
  116.     extern char *optarg;            /* for getopt */
  117.     extern int optind;              /* for getopt */
  118.     char c;                    /* for getopt */
  119.  
  120.     if(argc <=1)
  121.         usage();
  122.     /* 
  123.     ** print out a line at at time 
  124.     */
  125. #ifdef SYSV
  126.     setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
  127. #else
  128.     setlinebuf(stdout);
  129. #endif
  130.     signal(SIGINT, dostats);
  131.     res_init();
  132.     /* 
  133.     ** the name server names will be fully qualified 
  134.     */
  135.     _res.options &= ~(RES_DNSRCH|RES_DEFNAMES);
  136.     /* 
  137.     ** keep down the retransmissions 
  138.     */
  139.     _res.retry = 2;
  140.     /* 
  141.     ** send packet; wait 20 seconds; send packet wait 40 seconds 
  142.     ** (this can be tuned down on a local network)
  143.     */
  144.     _res.retrans = 20;
  145.     res_save = _res;
  146.     buildservicelist();
  147.     buildprotolist();
  148.  
  149.         zone.z_serial = 0;
  150.         zone.z_origin = "";
  151.         zone.z_type = Z_PRIMARY;
  152.         zone.z_class = C_IN;
  153.  
  154.     while ((c = getopt(argc, argv, "Ff:o:v")) != EOF)
  155.         switch(c){
  156.             case 'F':
  157.                     _res.retrans = 5;
  158.                     res_save = _res;
  159.                     break;
  160.             case 'f':
  161.                     errs +=db_load(optarg,
  162.                                                        zone.z_origin,
  163.                                                        &zone,
  164.                                                        NULL);
  165.                     break;
  166.             case 'o':
  167.                             zone.z_origin = optarg;
  168.                     break;
  169.             case 'v':
  170.                     verbose++;
  171.                     break;
  172.             case '?':
  173.                     usage();
  174.                     break;
  175.         }
  176.     dostats();
  177. }
  178.  
  179. /*
  180. ** Replacement routine to check NS records
  181. ** instead of actually adding the data to
  182. ** the hash tables.
  183. */
  184. int
  185. db_update(name, odp, newdp, flags, htp)
  186.     char name[];
  187.     struct databuf *odp, *newdp;
  188.     int flags;
  189.     struct hashbuf *htp;
  190. {
  191.     int i, j, n, failure;
  192.     HEADER *header;
  193.  
  194.     /* 
  195.     ** only look at NS records 
  196.     */
  197.     if(newdp->d_type == T_NS){
  198.  
  199.         /* 
  200.         ** Reset _res structure for gethostbyname
  201.         ** in case it is later modified
  202.         */
  203.         _res = res_save;
  204.         failure = 0;
  205.  
  206.         /*
  207.         ** Skip over servers that aren't running
  208.         ** or haven't responded.  
  209.         */
  210.         for(j = 0; j < noresponse; j++)
  211.             if(strcasecmp(newdp->d_data, string_resp[j]) == 0){
  212.                 if(verbose > 0)
  213.                     printf("Skipping %s\n", newdp->d_data);
  214.                 goto skip;
  215.             }
  216.         for(j = 0; j < notrunning; j++)
  217.             if(strcasecmp(newdp->d_data, string_run[j]) == 0){
  218.                 if(verbose > 0)
  219.                     printf("Skipping %s\n", newdp->d_data);
  220.                 goto skip;
  221.             }
  222.         hp = gethostbyname(newdp->d_data);
  223.         if(hp == NULL){
  224.             printf("No address for %s\n", newdp->d_data);
  225.         } else {
  226.             /* 
  227.             **try each address 
  228.             */
  229.             for(i = 0; hp->h_addr_list[i]; i++){
  230.                   memcpy((caddr_t)&sin.sin_addr, 
  231.                     hp->h_addr_list[i],
  232.                     hp->h_length);
  233.                 if(verbose > 1)
  234.                     printf("address %s\n", 
  235.                     inet_ntoa(sin.sin_addr));
  236.  
  237.                 /* 
  238.                 ** make SOA query 
  239.                 */
  240.                 n = res_mkquery(QUERY, name, C_IN, T_SOA, 
  241.                     NULL, 0, NULL, query, PACKETSZ);
  242.                 if(n < 0){
  243.                     fprintf(stderr, "res_mkquery failed\n");
  244.                     continue;
  245.                 }
  246.                 header = (HEADER *) query;
  247.  
  248.                 /* 
  249.                 ** turn off recursion desired bit so
  250.                 ** the server does not go out and
  251.                 ** find the SOA data
  252.                 */
  253.                 header->rd = 0;
  254.  
  255.                 /* 
  256.                 ** use only 1 address to get proper errno 
  257.                 ** to determine if server was or wasn't
  258.                 ** running
  259.                 */
  260.                     _res.nsaddr_list[0].sin_addr = 
  261.                             sin.sin_addr;
  262.                     _res.nscount = 1;
  263.                 errno = 0;
  264.                 n = res_send(query, n, response, PACKETSZ);
  265.  
  266.                 if(verbose > 1)
  267.                     fp_query(response,stdout);
  268.                 if(n > 0) {
  269.                         for(j = 0; j < mayberunning; j++)
  270.                             if((string_maybe[j] != NULL) &&
  271.                                            !strcasecmp(newdp->d_data, string_maybe[j])){
  272.                         if(verbose > 0)
  273.                             printf("\tServer %s moved off of maybe list\n",
  274.                             string_maybe[j]);
  275.                         free(string_maybe[j]);
  276.                         string_maybe[j] = NULL;
  277.                     }
  278.                     header = (HEADER *) response;
  279.                     if (header->rcode == SERVFAIL){
  280.                     servfail++;
  281.                     printf("SERVFAIL response from %s (domain %s)\n",
  282.                         newdp->d_data, name);
  283.                     /*
  284.                     ** authoritative server will have aa bit
  285.                     ** on and something in the answer section
  286.                     */
  287.                     } else if ((header->aa != 1) ||
  288.                     (ntohs(header->ancount) == 0)){
  289.                     badresp++;
  290.                     printf("Server %s is not authoritative for %s\n",
  291.                         newdp->d_data, name);
  292.                     } else {
  293.                     goodresp++;
  294.                     if(verbose > 0)
  295.                         printf("Server %s is authoritative for %s\n",
  296.                         newdp->d_data, name);
  297.                     }
  298.                     break;
  299.                 } else {
  300.                     failure = errno;
  301.                     /* 
  302.                     ** server not running, don't
  303.                     ** bother trying other addresses
  304.                     */
  305.                     if(errno == ECONNREFUSED)
  306.                     break;
  307.                 }
  308.             }
  309.             if((verbose > 0) && (failure == ECONNREFUSED)){
  310.                 printf("No name server running on %s (domain %s)\n",
  311.                         newdp->d_data, name);
  312.             } else {
  313.                 if((verbose > 0) && (failure == ETIMEDOUT))
  314.                     printf("No response from %s (domain %s)\n",
  315.                         newdp->d_data, name);
  316.             }
  317.             /* 
  318.             ** keep track of servers not running or not responding 
  319.             */
  320.             if((failure == ECONNREFUSED) && (notrunning < 200))
  321.                 string_run[notrunning++] = 
  322.                         savestr(newdp->d_data);
  323.             if((failure == ETIMEDOUT) && (mayberunning < 200)){
  324.                 int found;
  325.                 found = 0;
  326.                 for(j = 0; j < mayberunning; j++){
  327.                 if(string_maybe[j] == NULL)
  328.                     continue;
  329.                     if(!strcasecmp(newdp->d_data, string_maybe[j])){
  330.                     if(noresponse < 200){
  331.                     if(verbose > 0)
  332.                         printf("\tServer %s moved to not responding list\n",
  333.                             string_maybe[j]);
  334.                         string_resp[noresponse++] =
  335.                             string_maybe[j];
  336.                     }
  337.                     found = 1;
  338.                     break;
  339.                 }
  340.                 }
  341.                 if(found == 0){
  342.                 if(verbose > 0)
  343.                     printf("\tServer %s put on maybe list\n",
  344.                         newdp->d_data);
  345.                 string_maybe[mayberunning++] = 
  346.                         savestr(newdp->d_data);
  347.                 }
  348.             }
  349.  
  350.         }
  351.     } 
  352.     skip:
  353.     free(newdp);
  354.     return(0);
  355. }
  356.  
  357. /*
  358. ** Misc routines necessary to compile
  359. */
  360.  
  361. struct databuf *
  362. savedata(class, type, ttl, data, size)
  363.     int class, type;
  364.     u_int32_t ttl;
  365.     u_char *data;
  366.     int size;
  367. {
  368.     register struct databuf *dp;
  369.     int bytes = (type == T_NS) ? DATASIZE(size)+INT32SZ : DATASIZE(size);
  370.  
  371.     dp = (struct databuf *) malloc(bytes);
  372.     if (dp == NULL)
  373.         panic(errno, "savedata: malloc");
  374.     bzero((char*)dp, bytes);
  375.     dp->d_next = NULL;
  376.     dp->d_type = type;
  377.     dp->d_class = class;
  378.     dp->d_ttl = ttl;
  379.     dp->d_size = size;
  380.     dp->d_mark = 0;
  381.     dp->d_flags = 0;
  382.     dp->d_cred = 0;
  383.     dp->d_clev = 0;
  384. #ifdef NCACHE
  385.     dp->d_rcode = NOERROR;
  386. #endif
  387. #ifdef STATS
  388.     dp->d_ns = NULL;
  389. #endif
  390.     dp->d_nstime = 0;
  391.     bcopy(data, dp->d_data, dp->d_size);
  392.     return (dp);
  393. }
  394.  
  395. const char *
  396. zoneTypeString(zp)
  397.     const struct zoneinfo *zp;
  398. {
  399.     static char ret[sizeof "(4294967296?)"];    /* 2^32 */
  400.  
  401.     switch (zp->z_type) {
  402.     case Z_PRIMARY:        return ("primary");
  403.     case Z_SECONDARY:    return ("secondary");
  404. #ifdef STUBS
  405.     case Z_STUB:        return ("stub");
  406. #endif
  407.     case Z_CACHE:        return ("cache");
  408.     default:
  409.         sprintf(ret, "(%lu?)", (u_long)zp->z_type);
  410.         return (ret);
  411.     }
  412. }
  413.  
  414. #if 0
  415. void
  416. gettime(ttp)
  417. struct timeval *ttp;
  418. {
  419.     if (gettimeofday(ttp, (struct timezone *)0) < 0)
  420.         syslog(LOG_ERR, "gettimeofday failed: %m");
  421.     return;
  422. }
  423. #endif
  424.  
  425. u_int32_t
  426. net_mask()
  427. {
  428.     return(0);
  429. }
  430.  
  431. extern char *sys_errlist[];
  432. extern int errno;
  433.  
  434. syslog(a,b,c,d,e,f)
  435. int  a;
  436. char *b, *c, *d, *e, *f;
  437. {
  438.     int percent=0;
  439.     int position=0;
  440.     char *s;
  441.     int tmperrno;
  442.     char msg[256];
  443.  
  444.     tmperrno=errno;
  445.  
  446.     /*
  447.      * Copy the string in case
  448.      * it is modified by the next
  449.      * step.
  450.      */
  451.     strcpy(msg,b);
  452.     for(s=msg; *s!=NULL; s++)
  453.         if(*s == '%'){
  454.             percent++;
  455.             if(*(s+1) == 'm'){
  456.                 *(s+1) = 's';
  457.                 position=percent;
  458.             }
  459.         }
  460.     switch(position){
  461.         case 0: fprintf(stdout,msg,c,d,e,f); break;
  462.         case 1: fprintf(stdout,msg,sys_errlist[tmperrno],c,d,e,f); break;
  463.         case 2: fprintf(stdout,msg,c,sys_errlist[tmperrno],d,e,f); break;
  464.         case 3: fprintf(stdout,msg,c,d,sys_errlist[tmperrno],e,f); break;
  465.         case 4: fprintf(stdout,msg,c,d,e,sys_errlist[tmperrno],f); break;
  466.         case 5: fprintf(stdout,msg,c,d,e,f,sys_errlist[tmperrno]); break;
  467.         default: fprintf(stdout,"percent m in position %d\n",position); break;
  468.     }
  469.     fprintf(stdout,"\n");
  470. }
  471.  
  472. openlog()
  473. {}
  474.  
  475. /*
  476. ** Fake stubs for findnetinfo and printnetinfo to satisfy the compiler
  477. */
  478.  
  479. struct netinfo *
  480. findnetinfo(addr)
  481.     struct in_addr addr;
  482. {
  483.     return((struct netinfo *) NULL);
  484. }
  485.  
  486. printnetinfo(ntp)
  487.     register struct netinfo *ntp;
  488. {
  489.     return(1);
  490. }
  491.  
  492. int
  493. build_secure_netlist(zp)
  494.     struct zoneinfo *zp;
  495. {
  496. }
  497.  
  498. void
  499. ns_refreshtime(zp, timebase)
  500.     struct zoneinfo    *zp;
  501.     time_t        timebase;
  502. {
  503. }
  504.